#include "sqlite3.h"

#include "sqlite3_connection.hpp"

namespace topdbs
{
	sqlite3_connection::sqlite3_connection()
		: m_pConnection(nullptr)
		, m_isTransaction(false)
	{
	};

	sqlite3_connection::~sqlite3_connection()
	{
		disConnect();
	};

	int  sqlite3_connection::connect(
		eDBSClient_t dbsClientType,
		const string& dbString,
		const string& user,
		const string& pass,
		void* pOptio ) 
	{
		string host;
		int port;
		m_dbsClient = dbsClientType;
		topdbs_dbstring_parse(dbString,m_dbname,host,port);	

		try
		{
			if( strcasecmp(m_charset.c_str(),"GBK") != 0 
			&& strcasecmp(m_charset.c_str(),"GB18030") != 0 
			&& strcasecmp(m_charset.c_str(),"GB2312") != 0)
			{
				sqlite_client_encode = SQLIT_UTF8;
			}
			disConnect();
			int rc = sqlite3_open(m_dbname.c_str(),&m_pConnection);
			if(rc != SQLITE_OK)
			{
				sqliteErr(m_pConnection,m_sqlcode,m_sqlerr);
				dbslog(DBS_ERROR,"session_create(%s) ConnectionFailedException %s !",m_dbname.c_str(),m_sqlerr.c_str());
				return ERR_DBS_FAIL;
			}        
		}
		catch(const std::exception& e)
		{
			dbslog(DBS_ERROR,"connect() new ITConnection Exception %s !!",e.what());
			return ERR_DBS_FAIL;
		}  
		return ERR_DBS_OK;
	};

	bool sqlite3_connection::isConnected()  
	{
		return m_pConnection ? true : false;
	};

	int  sqlite3_connection::reConnect()  
	{
		disConnect();
		if(!m_pConnection)
		{
			int rc = sqlite3_open(m_dbname.c_str(),&m_pConnection);
			if(rc != SQLITE_OK)
			{
				sqliteErr(m_pConnection,m_sqlcode,m_sqlerr);
				dbslog(DBS_ERROR,"session_create(%s) ConnectionFailedException %s !",m_dbname.c_str(),m_sqlerr.c_str());
				return ERR_DBS_FAIL;
			}  		
		}
		return ERR_DBS_OK;
	};

	int  sqlite3_connection::disConnect()  
	{
		if(m_pConnection)
		{
			if(isTransaction())
			{
				rollback();
			}		
			sqlite3_close(m_pConnection);
			m_pConnection = nullptr;
		}
		return ERR_DBS_OK;
	};	

	int  sqlite3_connection::begin() 
	{
		CHK_SESSION_HANDLE_ERROR_RETURN(m_pConnection,ERR_DBS_UNKOWN);
		if(isTransaction())
		{
			return ERR_DBS_OK;
		}
		char* psErr = nullptr;
		if( sqlite3_exec(m_pConnection, "begin;", 0, 0, &psErr) != SQLITE_OK)
		{
			sqliteErr(m_pConnection,m_sqlcode,m_sqlerr);
			dbslog(DBS_ERROR,"begin() TransactionException erortext[%s]",psErr);
			return ERR_DBS_FAIL;
		}
		m_isTransaction = true;
		return ERR_DBS_OK;
	};

	int  sqlite3_connection::commit() 
	{
		CHK_SESSION_HANDLE_ERROR_RETURN(m_pConnection,ERR_DBS_UNKOWN);
		if(!isTransaction())
		{
			return ERR_DBS_OK;
		}
		char* psErr = nullptr;
		if( sqlite3_exec(m_pConnection, "commit;", 0, 0, &psErr) != SQLITE_OK)
		{
			sqliteErr(m_pConnection,m_sqlcode,m_sqlerr);
			dbslog(DBS_ERROR,"commit() TransactionException erortext[%s]",psErr);
			return ERR_DBS_FAIL;
		}
		m_isTransaction = false;
		return ERR_DBS_OK;
	};

	int  sqlite3_connection::rollback() 
	{
		CHK_SESSION_HANDLE_ERROR_RETURN(m_pConnection,ERR_DBS_UNKOWN);
		if(!isTransaction())
		{
			return ERR_DBS_OK;
		}
		char* psErr = nullptr;
		if( sqlite3_exec(m_pConnection, "rollback;", 0, 0, &psErr) != SQLITE_OK)
		{
			sqliteErr(m_pConnection,m_sqlcode,m_sqlerr);
			dbslog(DBS_ERROR,"rollback() TransactionException erortext[%s]",psErr);
			return ERR_DBS_FAIL;
		}
		m_isTransaction = false;
		return ERR_DBS_OK;
	};

	bool sqlite3_connection::isTransaction() 
	{
		CHK_SESSION_HANDLE_ERROR_RETURN(m_pConnection,false);
		return  m_isTransaction;
	};

	int  sqlite3_connection::autoCommit(bool on)  
	{
		CHK_SESSION_HANDLE_ERROR_RETURN(m_pConnection,ERR_DBS_UNKOWN);
		return ERR_DBS_OK;
	};

	void* sqlite3_connection::getConnection()
	{
		return m_pConnection;
	}

	void* sqlite3_connection::from_this()
	{
		return this;
	}

	int  sqlite3_connection::lockwait()
	{
		if(m_locktime < 1 )
		{
			char* psEnvLockTime = getenv("DB_LOCK_WAIT_TIME");
			if(psEnvLockTime)
			{
				m_locktime = atoi(psEnvLockTime); 
			}		
		}
		if(m_locktime == 0 || m_locktime > 900 ) 
		{
			m_locktime = TOPDBS_DEFAULT_LOCK_WAIT_TIME;
		}
		return ERR_DBS_OK;
	}

	int sqlite3_connection::get_lockwait()
	{
		lockwait();
		return m_locktime;
	}
}